home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Diamond Collection / The Diamond Collection (Software Vault)(Digital Impact).ISO / cdr44 / frasrc19.zip / PROMPTS2.C < prev    next >
C/C++ Source or Header  |  1995-03-04  |  61KB  |  2,146 lines

  1. /*
  2.     Various routines that prompt for things.
  3. */
  4.  
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <ctype.h>
  9. #ifndef XFRACT
  10. #include <io.h>
  11. #include <dos.h>
  12. #elif !defined(__386BSD__)
  13. #include <sys/types.h>
  14. #include <sys/stat.h>
  15. #include <sys/dir.h>
  16. #endif
  17. #ifdef __TURBOC__
  18. #include <alloc.h>
  19. #elif !defined(__386BSD__)
  20. #include <malloc.h>
  21. #endif
  22.  
  23. #ifdef __hpux
  24. #include <sys/param.h>
  25. #define getwd(a) getcwd(a,MAXPATHLEN)
  26. #endif
  27.  
  28. #include "fractint.h"
  29. #include "fractype.h"
  30. #include "helpdefs.h"
  31. #include "prototyp.h"
  32.  
  33. /* Routines in this module    */
  34.  
  35. static  int check_f6_key(int curkey,int choice);
  36. static    int expand_dirname(char *dirname,char *drive);
  37. static    int filename_speedstr(int, int, int, char *, int);
  38.  
  39. /* speed key state values */
  40. #define MATCHING     0    /* string matches list - speed key mode */
  41. #define TEMPLATE    -2    /* wild cards present - buiding template */
  42. #define SEARCHPATH    -3    /* no match - building path search name */
  43.  
  44. #define   FILEATTR     0x37       /* File attributes; select all but volume labels */
  45. #define   HIDDEN     2
  46. #define   SYSTEM     4
  47. #define   SUBDIR     16
  48. #define   MAXNUMFILES     2977L
  49.  
  50. struct DIR_SEARCH DTA;        /* Allocate DTA and define structure */
  51.  
  52. #define GETFORMULA 0
  53. #define GETLSYS    1
  54. #define GETIFS       2
  55. #define GETPARM    3
  56.  
  57. char commandmask[13] = {"*.par"};
  58.  
  59. /* --------------------------------------------------------------------- */
  60. /*
  61.     get_toggles() is called from FRACTINT.C whenever the 'x' key
  62.     is pressed.  This routine prompts for several options,
  63.     sets the appropriate variables, and returns the following code
  64.     to the calling routine:
  65.  
  66.     -1  routine was ESCAPEd - no need to re-generate the image.
  67.      0  nothing changed, or minor variable such as "overwrite=".
  68.         No need to re-generate the image.
  69.      1  major variable changed (such as "inside=").  Re-generate
  70.         the image.
  71.  
  72.     Finally, remember to insert variables in the list *and* check
  73.     for them in the same order!!!
  74. */
  75. #define LOADCHOICES(X)     {\
  76.    static FCODE tmp[] = { X };\
  77.    far_strcpy(ptr,(char far *)tmp);\
  78.    choices[++k]= ptr;\
  79.    ptr += sizeof(tmp);\
  80.    }
  81. int get_toggles()
  82. {
  83.    static FCODE o_hdg[]={"        Basic Options\n\
  84. (not all combinations make sense)"};
  85.    char hdg[sizeof(o_hdg)];
  86.    char far *choices[20];
  87.    char far *ptr;
  88.    int oldhelpmode;
  89.    char prevsavename[81];
  90.    char *savenameptr;
  91.    struct fullscreenvalues uvalues[25];
  92.    int i, j, k;
  93.    char old_usr_stdcalcmode;
  94.    long old_maxit;
  95.    int old_inside,old_outside,old_soundflag;
  96.    int old_logflag,old_biomorph,old_decomp;
  97.    int old_fillcolor;
  98.    static char *calcmodes[] ={"1","2","3","g","b","t"};
  99.    static char *soundmodes[5]={s_yes,s_no,s_x,s_y,s_z};
  100.  
  101.    far_strcpy(hdg,o_hdg);
  102.    ptr = (char far *)MK_FP(extraseg,0);
  103.  
  104.    k = -1;
  105.  
  106.    LOADCHOICES("Passes (1, 2, 3, g[uessing], b[oundary trace], t[esseral])");
  107.    uvalues[k].type = 'l';
  108.    uvalues[k].uval.ch.vlen = 3;
  109.    uvalues[k].uval.ch.llen = sizeof(calcmodes)/sizeof(*calcmodes);
  110.    uvalues[k].uval.ch.list = calcmodes;
  111.    uvalues[k].uval.ch.val = (usr_stdcalcmode == '1') ? 0
  112.               : (usr_stdcalcmode == '2') ? 1
  113.               : (usr_stdcalcmode == '3') ? 2
  114.                           : (usr_stdcalcmode == 'g') ? 3
  115.                           : (usr_stdcalcmode == 'b') ? 4 :5 ;
  116.    old_usr_stdcalcmode = usr_stdcalcmode;
  117.  
  118.    LOADCHOICES("Floating Point Algorithm");
  119.    uvalues[k].type = 'y';
  120.    uvalues[k].uval.ch.val = usr_floatflag;
  121.  
  122.    LOADCHOICES("Maximum Iterations (2 to 2,147,483,647)");
  123.    uvalues[k].type = 'L';
  124.    uvalues[k].uval.Lval = old_maxit = maxit;
  125.  
  126.    LOADCHOICES("Inside Color (<nnn>,maxiter,zmag,bof60,bof61,epscr,star,per)");
  127.    uvalues[k].type = 's';
  128.    if(inside == -59)
  129.       strcpy(uvalues[k].uval.sval,s_zmag);
  130.    else if(inside == -60)
  131.       strcpy(uvalues[k].uval.sval,s_bof60);
  132.    else if(inside == -61)
  133.       strcpy(uvalues[k].uval.sval,s_bof61);
  134.    else if(inside == -100)
  135.       strcpy(uvalues[k].uval.sval,s_epscross);
  136.    else if(inside == -101)
  137.       strcpy(uvalues[k].uval.sval,s_startrail);
  138.    else if(inside == -102)
  139.       strcpy(uvalues[k].uval.sval,s_period);
  140.    else if(inside == -1)
  141.       strcpy(uvalues[k].uval.sval,s_maxiter);
  142.    else
  143.       sprintf(uvalues[k].uval.sval,"%d",inside);
  144.    old_inside = inside;
  145.  
  146.    LOADCHOICES("Outside Color (<nnn>,iter,real,imag,mult,summ,atan)");
  147.    uvalues[k].type = 's';
  148.    if(outside == -1)
  149.       strcpy(uvalues[k].uval.sval,s_iter);
  150.    else if(outside == -2)
  151.       strcpy(uvalues[k].uval.sval,s_real);
  152.    else if(outside == -3)
  153.       strcpy(uvalues[k].uval.sval,s_imag);
  154.    else if(outside == -4)
  155.       strcpy(uvalues[k].uval.sval,s_mult);
  156.    else if(outside == -5)
  157.       strcpy(uvalues[k].uval.sval,s_sum);
  158.    else if(outside == -6)
  159.       strcpy(uvalues[k].uval.sval,s_atan);
  160.    else
  161.       sprintf(uvalues[k].uval.sval,"%d",outside);
  162.    old_outside = outside;
  163.  
  164.    LOADCHOICES("Savename (.GIF implied)");
  165.    uvalues[k].type = 's';
  166.    strcpy(prevsavename,savename);
  167.    savenameptr = strrchr(savename, SLASHC);
  168.    if(savenameptr == NULL)
  169.       savenameptr = savename;
  170.    else
  171.       savenameptr++; /* point past slash */   
  172.    strcpy(uvalues[k].uval.sval,savenameptr);
  173.  
  174.    LOADCHOICES("File Overwrite ('overwrite=')");
  175.    uvalues[k].type = 'y';
  176.    uvalues[k].uval.ch.val = overwrite;
  177.  
  178.    LOADCHOICES("Sound (no, yes, x, y, z)");
  179.    uvalues[k].type = 'l';
  180.    uvalues[k].uval.ch.vlen = 3;
  181.    uvalues[k].uval.ch.llen = 5;
  182.    uvalues[k].uval.ch.list = soundmodes;
  183.    uvalues[k].uval.ch.val = 1 + (old_soundflag = soundflag);
  184.  
  185.    if (rangeslen == 0) {
  186.       LOADCHOICES("Log Palette (0=no,1=yes,-1=old,+n=cmprsd,-n=sqrt, 2=auto)");
  187.       uvalues[k].type = 'i';
  188.       }
  189.    else {
  190.       LOADCHOICES("Log Palette (n/a, ranges= parameter is in effect)");
  191.       uvalues[k].type = '*';
  192.       }
  193.    uvalues[k].uval.ival = old_logflag = LogFlag;
  194.  
  195.    LOADCHOICES("Biomorph Color (-1 means OFF)");
  196.    uvalues[k].type = 'i';
  197.    uvalues[k].uval.ival = old_biomorph = usr_biomorph;
  198.  
  199.    LOADCHOICES("Decomp Option (2,4,8,..,256, 0=OFF)");
  200.    uvalues[k].type = 'i';
  201.    uvalues[k].uval.ival = old_decomp = decomp[0];
  202.  
  203.    LOADCHOICES("Fill Color (normal,<nnn>) (works with passes=t and =b)");
  204.    uvalues[k].type = 's';
  205.    if(fillcolor < 0)
  206.       strcpy(uvalues[k].uval.sval,s_normal);
  207.    else
  208.       sprintf(uvalues[k].uval.sval,"%d",fillcolor);
  209.    old_fillcolor = fillcolor;
  210.  
  211.    LOADCHOICES("Orbit delay (0 = none)");
  212.    uvalues[k].type = 'i';
  213.    uvalues[k].uval.ival = orbit_delay;
  214.  
  215.    oldhelpmode = helpmode;
  216.    helpmode = HELPXOPTS;
  217.    i = fullscreen_prompt(hdg,k+1,choices,uvalues,0,NULL);
  218.    helpmode = oldhelpmode;
  219.    if (i < 0) {
  220.       return(-1);
  221.       }
  222.  
  223.    /* now check out the results (*hopefully* in the same order <grin>) */
  224.    k = -1;
  225.    j = 0;   /* return code */
  226.  
  227.    usr_stdcalcmode = calcmodes[uvalues[++k].uval.ch.val][0];
  228.    if (old_usr_stdcalcmode != usr_stdcalcmode) j = 1;
  229.  
  230.    if (uvalues[++k].uval.ch.val != usr_floatflag) {
  231.       usr_floatflag = (char)uvalues[k].uval.ch.val;
  232.       j = 1;
  233.       }
  234.  
  235.    ++k;
  236.    maxit = uvalues[k].uval.Lval;
  237.    if (maxit < 0) maxit = old_maxit;
  238.    if (maxit < 2) maxit = 2;
  239.  
  240. /* 'maxit' is an int so it is always <= 32767, MCP 12-3-91
  241.    if (maxit > 32767) maxit = 32767;
  242. */
  243.  
  244.    if (maxit != old_maxit) j = 1;
  245.  
  246.    if(strncmp(strlwr(uvalues[++k].uval.sval),s_zmag,4)==0)
  247.       inside = -59;
  248.    else if(strncmp(strlwr(uvalues[k].uval.sval),s_bof60,5)==0)
  249.       inside = -60;
  250.    else if(strncmp(strlwr(uvalues[k].uval.sval),s_bof61,5)==0)
  251.       inside = -61;
  252.    else if(strncmp(strlwr(uvalues[k].uval.sval),s_epscross,3)==0)
  253.       inside = -100;
  254.    else if(strncmp(strlwr(uvalues[k].uval.sval),s_startrail,4)==0)
  255.       inside = -101;
  256.    else if(strncmp(strlwr(uvalues[k].uval.sval),s_period,3)==0)
  257.       inside = -102;
  258.    else if(strncmp(strlwr(uvalues[k].uval.sval),s_maxiter,5)==0)
  259.       inside = -1;
  260.    else
  261.       inside = atoi(uvalues[k].uval.sval);
  262.    if (inside != old_inside) j = 1;
  263.  
  264.    if(strncmp(strlwr(uvalues[++k].uval.sval),s_real,4)==0)
  265.       outside = -2;
  266.    else if(strncmp(strlwr(uvalues[k].uval.sval),s_imag,4)==0)
  267.       outside = -3;
  268.    else if(strncmp(strlwr(uvalues[k].uval.sval),s_mult,4)==0)
  269.       outside = -4;
  270.    else if(strncmp(strlwr(uvalues[k].uval.sval),s_sum,4)==0)
  271.       outside = -5;
  272.    else if(strncmp(strlwr(uvalues[k].uval.sval),s_atan,4)==0)
  273.       outside = -6;
  274.    else if(strncmp(strlwr(uvalues[k].uval.sval),s_iter,4)==0)
  275.       outside = -1;
  276.    else
  277.       outside = atoi(uvalues[k].uval.sval);
  278.    if (outside != old_outside) j = 1;
  279.  
  280.    strcpy(savenameptr,uvalues[++k].uval.sval);
  281.    if (strcmp(savename,prevsavename))
  282.       resave_flag = started_resaves = 0; /* forget pending increment */
  283.    overwrite = (char)uvalues[++k].uval.ch.val;
  284.  
  285.    soundflag = uvalues[++k].uval.ch.val - 1;
  286.    if (soundflag != old_soundflag && (soundflag > 1 || old_soundflag > 1))
  287.       j = 1;
  288.  
  289.    LogFlag = uvalues[++k].uval.ival;
  290.    if (LogFlag != old_logflag) j = 1;
  291.  
  292.    usr_biomorph = uvalues[++k].uval.ival;
  293.    if (usr_biomorph != old_biomorph) j = 1;
  294.  
  295.    decomp[0] = uvalues[++k].uval.ival;
  296.    if (decomp[0] != old_decomp) j = 1;
  297.  
  298.    if(strncmp(strlwr(uvalues[++k].uval.sval),s_normal,4)==0)
  299.       fillcolor = -1;
  300.    else
  301.       fillcolor = atoi(uvalues[k].uval.sval);
  302.    if (fillcolor != old_fillcolor) j = 1;
  303.  
  304.    orbit_delay = uvalues[++k].uval.ival;
  305.  
  306.    return(j);
  307. }
  308.  
  309. /*
  310.     get_toggles2() is similar to get_toggles, invoked by 'y' key
  311. */
  312.  
  313. int get_toggles2()
  314. {
  315.    static FCODE o_hdg[]={"       Extended Options\n\
  316. (not all combinations make sense)"};
  317.    char hdg[sizeof(o_hdg)];
  318.    char far *ptr;
  319.    char far *choices[20];
  320.    int oldhelpmode;
  321.  
  322.    struct fullscreenvalues uvalues[25];
  323.    int i, j, k;
  324.  
  325.    int old_rotate_lo,old_rotate_hi;
  326.    int old_usr_distest,old_distestwidth;
  327.    double old_potparam[3],old_inversion[3];
  328.  
  329.    far_strcpy(hdg,o_hdg);
  330.    ptr = (char far *)MK_FP(extraseg,0);
  331.  
  332.    /* fill up the choices (and previous values) arrays */
  333.    k = -1;
  334.  
  335.    LOADCHOICES("Look for finite attractor (0=no,>0=yes,<0=phase)");
  336.    uvalues[k].type = 'i';
  337.    uvalues[k].uval.ch.val = finattract;
  338.  
  339.    LOADCHOICES("Potential Max Color (0 means off)");
  340.    uvalues[k].type = 'i';
  341.    uvalues[k].uval.ival = (int)(old_potparam[0] = potparam[0]);
  342.  
  343.    LOADCHOICES("          Slope");
  344.    uvalues[k].type = 'd';
  345.    uvalues[k].uval.dval = old_potparam[1] = potparam[1];
  346.  
  347.    LOADCHOICES("          Bailout");
  348.    uvalues[k].type = 'i';
  349.    uvalues[k].uval.ival = (int)(old_potparam[2] = potparam[2]);
  350.  
  351.    LOADCHOICES("          16 bit values");
  352.    uvalues[k].type = 'y';
  353.    uvalues[k].uval.ch.val = pot16bit;
  354.  
  355.    LOADCHOICES("Distance Estimator (0=off, <0=edge, >0=on):");
  356.    uvalues[k].type = 'i';
  357.    uvalues[k].uval.ival = old_usr_distest = usr_distest;
  358.  
  359.    LOADCHOICES("          width factor:");
  360.    uvalues[k].type = 'i';
  361.    uvalues[k].uval.ival = old_distestwidth = distestwidth;
  362.  
  363.  
  364.  
  365.    LOADCHOICES("Inversion radius or \"auto\" (0 means off)");
  366.    LOADCHOICES("          center X coordinate or \"auto\"");
  367.    LOADCHOICES("          center Y coordinate or \"auto\"");
  368.    k = k - 3;
  369.    for (i= 0; i < 3; i++) {
  370.       uvalues[++k].type = 's';
  371.       if ((old_inversion[i] = inversion[i]) == AUTOINVERT)
  372.      sprintf(uvalues[k].uval.sval,"auto");
  373.       else
  374.      sprintf(uvalues[k].uval.sval,"%g",inversion[i]);
  375.       }
  376.    LOADCHOICES("  (use fixed radius & center when zooming)");
  377.    uvalues[k].type = '*';
  378.  
  379.    LOADCHOICES("Color cycling from color (0 ... 254)");
  380.    uvalues[k].type = 'i';
  381.    uvalues[k].uval.ival = old_rotate_lo = rotate_lo;
  382.  
  383.    LOADCHOICES("              to   color (1 ... 255)");
  384.    uvalues[k].type = 'i';
  385.    uvalues[k].uval.ival = old_rotate_hi = rotate_hi;
  386.  
  387.    oldhelpmode = helpmode;
  388.    helpmode = HELPYOPTS;
  389.    i = fullscreen_prompt(hdg,k+1,choices,uvalues,0,NULL);
  390.    helpmode = oldhelpmode;
  391.    if (i < 0) {
  392.       return(-1);
  393.       }
  394.  
  395.    /* now check out the results (*hopefully* in the same order <grin>) */
  396.    k = -1;
  397.    j = 0;   /* return code */
  398.  
  399.    if (uvalues[++k].uval.ch.val != finattract) {
  400.       finattract = uvalues[k].uval.ch.val;
  401.       j = 1;
  402.       }
  403.  
  404.    potparam[0] = uvalues[++k].uval.ival;
  405.    if (potparam[0] != old_potparam[0]) j = 1;
  406.  
  407.    potparam[1] = uvalues[++k].uval.dval;
  408.    if (potparam[0] != 0.0 && potparam[1] != old_potparam[1]) j = 1;
  409.  
  410.    potparam[2] = uvalues[++k].uval.ival;
  411.    if (potparam[0] != 0.0 && potparam[2] != old_potparam[2]) j = 1;
  412.  
  413.    if (uvalues[++k].uval.ch.val != pot16bit) {
  414.       pot16bit = uvalues[k].uval.ch.val;
  415.       if (pot16bit) { /* turned it on */
  416.      if (potparam[0] != 0.0) j = 1;
  417.      }
  418.       else /* turned it off */
  419.      if (dotmode != 11) /* ditch the disk video */
  420.         enddisk();
  421.      else /* keep disk video, but ditch the fraction part at end */
  422.         disk16bit = 0;
  423.       }
  424.  
  425.    ++k;
  426.    usr_distest = (uvalues[k].uval.ival > 32000) ? 32000 : uvalues[k].uval.ival;
  427.    if (usr_distest != old_usr_distest) j = 1;
  428.    ++k;
  429.    distestwidth = uvalues[k].uval.ival;
  430.    if (usr_distest && distestwidth != old_distestwidth) j = 1;
  431.  
  432.    for (i = 0; i < 3; i++) {
  433.       if (uvalues[++k].uval.sval[0] == 'a' || uvalues[k].uval.sval[0] == 'A')
  434.      inversion[i] = AUTOINVERT;
  435.       else
  436.      inversion[i] = atof(uvalues[k].uval.sval);
  437.       if (old_inversion[i] != inversion[i]
  438.     && (i == 0 || inversion[0] != 0.0))
  439.      j = 1;
  440.       }
  441.    invert = (inversion[0] == 0.0) ? 0 : 3;
  442.    ++k;
  443.  
  444.    rotate_lo = uvalues[++k].uval.ival;
  445.    rotate_hi = uvalues[++k].uval.ival;
  446.    if (rotate_lo < 0 || rotate_hi > 255 || rotate_lo > rotate_hi) {
  447.       rotate_lo = old_rotate_lo;
  448.       rotate_hi = old_rotate_hi;
  449.       }
  450.  
  451.    return(j);
  452. }
  453.  
  454. /* --------------------------------------------------------------------- */
  455. /*
  456.     get_view_params() is called from FRACTINT.C whenever the 'v' key
  457.     is pressed.  Return codes are:
  458.     -1  routine was ESCAPEd - no need to re-generate the image.
  459.      0  minor variable changed.  No need to re-generate the image.
  460.      1  View changed.  Re-generate the image.
  461. */
  462.  
  463. int get_view_params()
  464. {
  465.    static FCODE o_hdg[]={"View Window Options"};
  466.    char hdg[sizeof(o_hdg)];
  467.    char far *choices[8];
  468.    char far *ptr;
  469.  
  470.    int oldhelpmode;
  471.    struct fullscreenvalues uvalues[25];
  472.    int i, k;
  473.    float old_viewreduction,old_aspectratio;
  474.    int old_viewwindow,old_viewxdots,old_viewydots;
  475.  
  476.    far_strcpy(hdg,o_hdg);
  477.    ptr = (char far *)MK_FP(extraseg,0);
  478.  
  479.    old_viewwindow    = viewwindow;
  480.    old_viewreduction = viewreduction;
  481.    old_aspectratio   = finalaspectratio;
  482.    old_viewxdots     = viewxdots;
  483.    old_viewydots     = viewydots;
  484.  
  485. get_view_restart:
  486.    /* fill up the previous values arrays */
  487.    k = -1;
  488.  
  489.    LOADCHOICES("Preview display? (no for full screen)");
  490.    uvalues[k].type = 'y';
  491.    uvalues[k].uval.ch.val = viewwindow;
  492.  
  493.    LOADCHOICES("Auto window size reduction factor");
  494.    uvalues[k].type = 'f';
  495.    uvalues[k].uval.dval = viewreduction;
  496.  
  497.    LOADCHOICES("Final media overall aspect ratio, y/x");
  498.    uvalues[k].type = 'f';
  499.    uvalues[k].uval.dval = finalaspectratio;
  500.  
  501.    LOADCHOICES("Crop starting coordinates to new aspect ratio?");
  502.    uvalues[k].type = 'y';
  503.    uvalues[k].uval.ch.val = viewcrop;
  504.  
  505.    LOADCHOICES("Explicit size x pixels (0 for auto size)");
  506.    uvalues[k].type = 'i';
  507.    uvalues[k].uval.ival = viewxdots;
  508.  
  509.    LOADCHOICES("              y pixels (0 to base on aspect ratio)");
  510.    uvalues[k].type = 'i';
  511.    uvalues[k].uval.ival = viewydots;
  512.  
  513.    LOADCHOICES("");
  514.    uvalues[k].type = '*';
  515.  
  516.    LOADCHOICES("Press F4 to reset view parameters to defaults.");
  517.    uvalues[k].type = '*';
  518.  
  519.    oldhelpmode = helpmode;     /* this prevents HELP from activating */
  520.    helpmode = HELPVIEW;
  521.    i = fullscreen_prompt(hdg,k+1,choices,uvalues,16,NULL);
  522.    helpmode = oldhelpmode;     /* re-enable HELP */
  523.    if (i < 0) {
  524.       return(-1);
  525.       }
  526.  
  527.    if (i == F4) {
  528.       viewwindow = viewxdots = viewydots = 0;
  529.       viewreduction = (float)4.2;
  530.       viewcrop = 1;
  531.       finalaspectratio = screenaspect;
  532.       goto get_view_restart;
  533.       }
  534.  
  535.    /* now check out the results (*hopefully* in the same order <grin>) */
  536.    k = -1;
  537.  
  538.    viewwindow = uvalues[++k].uval.ch.val;
  539.  
  540.    viewreduction = (float)uvalues[++k].uval.dval;
  541.  
  542.    if ((finalaspectratio = (float)uvalues[++k].uval.dval) == 0)
  543.       finalaspectratio = screenaspect;
  544.  
  545.    viewcrop = uvalues[++k].uval.ch.val;
  546.  
  547.    viewxdots = uvalues[++k].uval.ival;
  548.    viewydots = uvalues[++k].uval.ival;
  549.  
  550.    if (finalaspectratio != old_aspectratio && viewcrop)
  551.       aspectratio_crop(old_aspectratio,finalaspectratio);
  552.  
  553.    i = 0;
  554.    if (viewwindow != old_viewwindow
  555.       || (viewwindow
  556.      && (  viewreduction != old_viewreduction
  557.         || finalaspectratio != old_aspectratio
  558.         || viewxdots != old_viewxdots
  559.         || (viewydots != old_viewydots && viewxdots) ) ) )
  560.       i = 1;
  561.  
  562.    return(i);
  563. }
  564.  
  565. /*
  566.     get_cmd_string() is called from FRACTINT.C whenever the 'g' key
  567.     is pressed.  Return codes are:
  568.     -1  routine was ESCAPEd - no need to re-generate the image.
  569.      0  parameter changed, no need to regenerate
  570.     >0  parameter changed, regenerate
  571. */
  572.  
  573. int get_cmd_string()
  574. {
  575.    static FCODE o_msg[] = {"Enter command string to use."};
  576.    char msg[sizeof(o_msg)];
  577.    int oldhelpmode;
  578.    int i;
  579.    char cmdbuf[61];
  580.  
  581.    far_strcpy(msg,o_msg);
  582.    oldhelpmode = helpmode;
  583.    helpmode = HELPCOMMANDS;
  584.    cmdbuf[0] = 0;
  585.    i = field_prompt(0,msg,NULL,cmdbuf,60,NULL);
  586.    helpmode = oldhelpmode;
  587.    if (i >= 0 && cmdbuf[0] != 0)
  588.        i = cmdarg(cmdbuf, 2);
  589.  
  590.    return(i);
  591. }
  592.  
  593.  
  594. /* --------------------------------------------------------------------- */
  595.  
  596. int Distribution = 30, Offset = 0, Slope = 25;
  597. long con;
  598.  
  599.  
  600.        double starfield_values[4] = {
  601.     30.0,100.0,5.0,0.0
  602.     };
  603.  
  604. char GreyFile[] = "altern.map";
  605.  
  606. int starfield(void)
  607. {
  608.    int c;
  609.    busy = 1;
  610.    if (starfield_values[0] <   1.0) starfield_values[0] =   1.0;
  611.    if (starfield_values[0] > 100.0) starfield_values[0] = 100.0;
  612.    if (starfield_values[1] <   1.0) starfield_values[1] =   1.0;
  613.    if (starfield_values[1] > 100.0) starfield_values[1] = 100.0;
  614.    if (starfield_values[2] <   1.0) starfield_values[2] =   1.0;
  615.    if (starfield_values[2] > 100.0) starfield_values[2] = 100.0;
  616.  
  617.    Distribution = (int)(starfield_values[0]);
  618.    con    = (long)(((starfield_values[1]) / 100.0) * (1L << 16));
  619.    Slope = (int)(starfield_values[2]);
  620.  
  621.    if (ValidateLuts(GreyFile) != 0) {
  622.       static FCODE msg[]={"Unable to load ALTERN.MAP"};
  623.       stopmsg(0,msg);
  624.       busy = 0;
  625.       return(-1);
  626.       }
  627.    spindac(0,1);         /* load it, but don't spin */
  628.    for(row = 0; row < ydots; row++) {
  629.       for(col = 0; col < xdots; col++) {
  630.      if(keypressed()) {
  631.         buzzer(1);
  632.         busy = 0;
  633.         return(1);
  634.         }
  635.      c = getcolor(col, row);
  636.          if(c == inside)
  637.             c = colors-1;
  638.      putcolor(col, row, GausianNumber(c, colors));
  639.       }
  640.    }
  641.    buzzer(0);
  642.    busy = 0;
  643.    return(0);
  644. }
  645.  
  646. int get_starfield_params(void) {
  647.    static FCODE o_hdg[]={"Starfield Parameters"};
  648.    static FCODE o_sf1[] = {"Star Density in Pixels per Star"};
  649.    static FCODE o_sf2[] = {"Percent Clumpiness"};
  650.    static FCODE o_sf3[] = {"Ratio of Dim stars to Bright"};
  651.    char hdg[sizeof(o_hdg)];
  652.    char sf1[sizeof(o_sf1)];
  653.    char sf2[sizeof(o_sf2)];
  654.    char sf3[sizeof(o_sf3)];
  655.    struct fullscreenvalues uvalues[3];
  656.    int oldhelpmode;
  657.    int i;
  658.    char far *starfield_prompts[3];
  659.    far_strcpy(hdg,o_hdg);
  660.    far_strcpy(sf1,o_sf1);
  661.    far_strcpy(sf2,o_sf2);
  662.    far_strcpy(sf3,o_sf3);
  663.    starfield_prompts[0] = sf1;
  664.    starfield_prompts[1] = sf2;
  665.    starfield_prompts[2] = sf3;
  666.  
  667.    if(colors < 255) {
  668.       static FCODE msg[]={"starfield requires 256 color mode"};
  669.       stopmsg(0,msg);
  670.       return(-1);
  671.    }
  672.    for (i = 0; i < 3; i++) {
  673.       uvalues[i].uval.dval = starfield_values[i];
  674.       uvalues[i].type = 'f';
  675.    }
  676.    stackscreen();
  677.    oldhelpmode = helpmode;
  678.    helpmode = HELPSTARFLD;
  679.    i = fullscreen_prompt(hdg,3,starfield_prompts,uvalues,0,NULL);
  680.    helpmode = oldhelpmode;
  681.    unstackscreen();
  682.    if (i < 0) {
  683.       return(-1);
  684.       }
  685.    for (i = 0; i < 3; i++)
  686.       starfield_values[i] = uvalues[i].uval.dval;
  687.  
  688.    return(0);
  689. }
  690.  
  691. static char *masks[] = {"*.pot","*.gif"};
  692.  
  693. int get_rds_params(void) {
  694.    static FCODE o_hdg[] =  {"Random Dot Stereogram Parameters"};
  695.    static FCODE o_rds0[] = {"Depth Effect (negative reverses front and back)"};
  696.    static FCODE o_rds1[] = {"Image width in inches"};
  697.    static FCODE o_rds2[] = {"Use grayscale value for depth? (if \"no\" uses color number)"};
  698.    static FCODE o_rds3[] = {"Calibration bars"};
  699.    static FCODE o_rds4[] = {"Use image map? (if \"no\" uses random dots)"};
  700.    static FCODE o_rds5[] = {"  If yes, use current image map name? (see below)"};
  701.    
  702.    char hdg[sizeof(o_hdg)];
  703.    char rds0[sizeof(o_rds0)];
  704.    char rds1[sizeof(o_rds1)];
  705.    char rds2[sizeof(o_rds2)];
  706.    char rds3[sizeof(o_rds3)];
  707.    char rds4[sizeof(o_rds4)];
  708.    char rds5[sizeof(o_rds5)];
  709.    char rds6[60];
  710.    static char *stereobars[] = {"none", "middle", "top"};
  711.    struct fullscreenvalues uvalues[7];
  712.    char far *rds_prompts[7];
  713.    int oldhelpmode;
  714.    int i,k;
  715.    int ret;
  716.    static char reuse = 0;
  717.    stackscreen();
  718.    for(;;)
  719.    {
  720.       ret = 0;
  721.       /* copy to make safe from overlay change */
  722.       far_strcpy(hdg,o_hdg);
  723.       far_strcpy(rds0,o_rds0);
  724.       far_strcpy(rds1,o_rds1);
  725.       far_strcpy(rds2,o_rds2);
  726.       far_strcpy(rds3,o_rds3);
  727.       far_strcpy(rds4,o_rds4);
  728.       far_strcpy(rds5,o_rds5);
  729.       rds_prompts[0] = rds0;
  730.       rds_prompts[1] = rds1;
  731.       rds_prompts[2] = rds2;
  732.       rds_prompts[3] = rds3;
  733.       rds_prompts[4] = rds4;
  734.       rds_prompts[5] = rds5;
  735.       rds_prompts[6] = rds6;
  736.       
  737.       k=0;
  738.       uvalues[k].uval.ival = AutoStereo_depth;
  739.       uvalues[k++].type = 'i';
  740.  
  741.       uvalues[k].uval.dval = AutoStereo_width;
  742.       uvalues[k++].type = 'f';
  743.  
  744.       uvalues[k].uval.ch.val = grayflag;
  745.       uvalues[k++].type = 'y';
  746.  
  747.       uvalues[k].type = 'l';
  748.       uvalues[k].uval.ch.list = stereobars;
  749.       uvalues[k].uval.ch.vlen = 6;
  750.       uvalues[k].uval.ch.llen = 3;
  751.       uvalues[k++].uval.ch.val  = calibrate;
  752.  
  753.       uvalues[k].uval.ch.val = image_map;
  754.       uvalues[k++].type = 'y';
  755.  
  756.  
  757.       if(isagif(stereomapname,xdots,ydots))
  758.       {
  759.          char *p;
  760.          uvalues[k].uval.ch.val = reuse;
  761.          uvalues[k++].type = 'y';
  762.  
  763.          uvalues[k++].type = '*';
  764.          for(i=0;i<sizeof(rds6);i++)
  765.             rds6[i] = ' ';
  766.          if((p = strrchr(stereomapname,'\\'))==NULL || 
  767.                  strlen(stereomapname) < sizeof(rds6)-2)
  768.             p = strlwr(stereomapname);
  769.          else
  770.             p++;
  771.          /* center file name */
  772.          rds6[(sizeof(rds6)-strlen(p)+2)/2] = 0;
  773.          strcat(rds6,"[");
  774.          strcat(rds6,p);
  775.          strcat(rds6,"]");
  776.       }
  777.       else
  778.          *stereomapname = 0;
  779.       oldhelpmode = helpmode;
  780.       helpmode = HELPRDS;
  781.       i = fullscreen_prompt(hdg,k,rds_prompts,uvalues,0,NULL);
  782.       helpmode = oldhelpmode;
  783.       if (i < 0) {
  784.          ret = -1;
  785.          break;
  786.          }
  787.       else
  788.       {
  789.          k=0;
  790.          AutoStereo_depth = uvalues[k++].uval.ival;
  791.          AutoStereo_width = uvalues[k++].uval.dval;
  792.          grayflag         = (char)uvalues[k++].uval.ch.val;
  793.          calibrate        = (char)uvalues[k++].uval.ch.val;
  794.          image_map        = (char)uvalues[k++].uval.ch.val;
  795.          if(*stereomapname)
  796.             reuse         = (char)uvalues[k++].uval.ch.val;
  797.          else
  798.             reuse = 0;   
  799.          if(image_map && !reuse)
  800.          {
  801.             static FCODE tmp[] = {"Select an Imagemap File\n(showing only "};
  802.             /* rds3 only a convenient buffer */
  803.             sprintf(rds3,"%Fs %dx%d GIFs)",(char far *)tmp,xdots,ydots);
  804.             if(getafilename(rds3,masks[1],stereomapname))
  805.                continue;
  806.          }            
  807.       }
  808.       break;      
  809.    }
  810.    unstackscreen();
  811.    return(ret);
  812. }
  813.  
  814. int get_a_number(double *x, double *y)
  815. {
  816.    static FCODE o_hdg[]={"Set Cursor Coordinates"};
  817.    char hdg[sizeof(o_hdg)];
  818.    char far *ptr;
  819.    char far *choices[2];
  820.  
  821.    struct fullscreenvalues uvalues[2];
  822.    int i, k;
  823.  
  824.    stackscreen();
  825.    far_strcpy(hdg,o_hdg);
  826.    ptr = (char far *)MK_FP(extraseg,0);
  827.  
  828.    /* fill up the previous values arrays */
  829.    k = -1;
  830.  
  831.    LOADCHOICES("X coordinate at cursor");
  832.    uvalues[k].type = 'd';
  833.    uvalues[k].uval.dval = *x;
  834.  
  835.    LOADCHOICES("Y coordinate at cursor");
  836.    uvalues[k].type = 'd';
  837.    uvalues[k].uval.dval = *y;
  838.  
  839.    i = fullscreen_prompt(hdg,k+1,choices,uvalues,25,NULL);
  840.    if (i < 0) {
  841.       unstackscreen();
  842.       return(-1);
  843.       }
  844.  
  845.    /* now check out the results (*hopefully* in the same order <grin>) */
  846.    k = -1;
  847.  
  848.    *x = uvalues[++k].uval.dval;
  849.    *y = uvalues[++k].uval.dval;
  850.  
  851.    unstackscreen();
  852.    return(i);
  853. }
  854.  
  855. /* --------------------------------------------------------------------- */
  856.  
  857. int get_commands()        /* execute commands from file */
  858. {
  859.    int ret;
  860.    FILE *parmfile;
  861.    long point;
  862.    int oldhelpmode;
  863.    ret = 0;
  864.    oldhelpmode = helpmode;
  865.    helpmode = HELPPARMFILE;
  866.    if ((point = get_file_entry(GETPARM,"Parameter Set",
  867.                    commandmask,CommandFile,CommandName)) >= 0
  868.      && (parmfile = fopen(CommandFile,"rb")) != NULL) {
  869.       fseek(parmfile,point,SEEK_SET);
  870.       ret = load_commands(parmfile);
  871.       }
  872.    helpmode = oldhelpmode;
  873.    return(ret);
  874. }
  875.  
  876. /* --------------------------------------------------------------------- */
  877.  
  878. void goodbye()            /* we done.  Bail out */
  879. {
  880.    char goodbyemessage[40];
  881.    int ret;
  882.    static FCODE gbm[]={"   Thank You for using FRACTINT"};
  883. #ifndef XFRACT
  884.    union REGS r;
  885. #endif
  886.    far_strcpy(goodbyemessage, gbm);
  887. #ifdef WINFRACT
  888.    return;
  889. #endif
  890.    
  891.    setvideotext();
  892. #ifdef XFRACT
  893.    UnixDone();
  894.    printf("\n\n\n%s\n",goodbyemessage); /* printf takes far pointer */
  895. #else
  896.    r.h.al = (char)((mode7text == 0) ? exitmode : 7);
  897.    r.h.ah = 0;
  898.    int86(0x10, &r, &r);
  899.    printf("\n\n\n%s\n",goodbyemessage); /* printf takes far pointer */
  900. #endif
  901.    movecursor(6,0);
  902.    discardgraphics(); /* if any emm/xmm tied up there, release it */
  903.    stopslideshow();
  904. #ifndef XFRACT
  905.    if (made_dsktemp)
  906.       dir_remove(tempdir,diskfilename);
  907. #endif
  908.    end_help();
  909.    ret = 0;
  910.    if (initbatch == 3) /* exit with error code for batch file */
  911.      ret = 2;
  912.    else if (initbatch == 4)
  913.      ret = 1;
  914.    exit(ret);
  915. }
  916.  
  917.  
  918. /* --------------------------------------------------------------------- */
  919.  
  920. #ifdef XFRACT
  921. static char searchdir[FILE_MAX_DIR];
  922. static char searchname[FILE_MAX_PATH];
  923. static char searchext[FILE_MAX_EXT];
  924. static DIR *currdir = NULL;
  925. #endif
  926. int  fr_findfirst(char *path)       /* Find 1st file (or subdir) meeting path/filespec */
  927. {
  928. #ifndef XFRACT
  929.      union REGS regs;
  930.      regs.h.ah = 0x1A;           /* Set DTA to filedata */
  931.      regs.x.dx = (unsigned)&DTA;
  932.      intdos(®s, ®s);
  933.      regs.h.ah = 0x4E;           /* Find 1st file meeting path */
  934.      regs.x.dx = (unsigned)path;
  935.      regs.x.cx = FILEATTR;
  936.      intdos(®s, ®s);
  937.      return(regs.x.ax);        /* Return error code */
  938. #else
  939.      if (currdir != NULL) {
  940.          closedir(currdir);
  941.          currdir = NULL;
  942.      }
  943.      splitpath(path,NULL,searchdir,searchname,searchext);
  944.      if (searchdir[0]=='\0') {
  945.          currdir = opendir(".");
  946.      } else {
  947.          currdir = opendir(searchdir);
  948.      }
  949.      if (currdir==NULL) {
  950.          return -1;
  951.      } else {
  952.          return fr_findnext();
  953.      }
  954. #endif
  955. }
  956.  
  957. int  fr_findnext()        /* Find next file (or subdir) meeting above path/filespec */
  958. {
  959. #ifndef XFRACT
  960.      union REGS regs;
  961.      regs.h.ah = 0x4F;           /* Find next file meeting path */
  962.      regs.x.dx = (unsigned)&DTA;
  963.      intdos(®s, ®s);
  964.      return(regs.x.ax);
  965. #else
  966. #ifdef DIRENT
  967.      struct dirent *dirEntry;
  968. #else
  969.      struct direct *dirEntry;
  970. #endif
  971.      struct stat sbuf;
  972.      char thisname[FILE_MAX_PATH];
  973.      char tmpname[FILE_MAX_PATH];
  974.      char thisext[FILE_MAX_EXT];
  975.      for(;;) {
  976.          dirEntry = readdir(currdir);
  977.          if (dirEntry == NULL) {
  978.              closedir(currdir);
  979.              currdir = NULL;
  980.              return -1;
  981.          } else if (dirEntry->d_ino != 0) {
  982.              splitpath(dirEntry->d_name,NULL,NULL,thisname,thisext);
  983.              if ((searchname[0]=='*' || strcmp(searchname,thisname)==0) &&
  984.                      (searchext[0]=='*' || strcmp(searchext,thisext)==0)) {
  985.                  strncpy(DTA.filename,dirEntry->d_name,20);
  986.                  DTA.filename[20]=='\0';
  987.                  strcpy(tmpname,searchdir);
  988.                  strcat(tmpname,"/");
  989.                  strcat(tmpname,dirEntry->d_name);
  990.                  stat(tmpname,&sbuf);
  991.                  if ((sbuf.st_mode&S_IFMT)==S_IFREG) {
  992.                      DTA.attribute = 0;
  993.                  } else if ((sbuf.st_mode&S_IFMT)==S_IFDIR) {
  994.                      DTA.attribute = SUBDIR;
  995.                  } else {
  996.                      continue;
  997.                  }
  998.                  DTA.size = sbuf.st_size;
  999.                  return 0;
  1000.              }
  1001.          }
  1002.      }
  1003. #endif
  1004. }
  1005.  
  1006.  
  1007. #if 0
  1008. void heap_sort(void far *ra1, int n, unsigned sz, int (__cdecl *fct)(VOIDFARPTR arg1,VOIDFARPTR arg2))
  1009. {
  1010.    int ll,j,ir,i;
  1011.    void far *rra;
  1012.    char far *ra;
  1013.    ra = (char far *)ra1;
  1014.    ra -= sz;
  1015.    ll=(n>>1)+1;
  1016.    ir=n;
  1017.    
  1018.    for(;;)
  1019.    {
  1020.       if(ll>1)
  1021.          rra = *((char far *far *)(ra+(--ll)*sz));
  1022.       else
  1023.       {
  1024.          rra = *((char far * far *)(ra+ir*sz));
  1025.          *((char far * far *)(ra+ir*sz))=*((char far * far *)(ra+sz));
  1026.          if(--ir == 1)
  1027.          {
  1028.             *((char far * far *)(ra+sz))=rra;
  1029.             return;
  1030.          }   
  1031.       }
  1032.       i = ll;
  1033.       j = ll <<1;
  1034.       while (j <= ir)
  1035.       {
  1036.          if(j<ir && (fct(ra+j*sz,ra+(j+1)*sz) < 0))
  1037.             ++j;
  1038.          if(fct(&rra,ra+j*sz) < 0)
  1039.          {
  1040.             *((char far * far *)(ra+i*sz)) = *((char far * far *)(ra+j*sz));
  1041.             j += (i=j);
  1042.          }   
  1043.          else
  1044.             j=ir+1;
  1045.       }
  1046.       *((char far * far *)(ra+i*sz))=rra;   
  1047.    }
  1048. }
  1049. #endif
  1050.  
  1051. int lccompare(VOIDFARPTR arg1, VOIDFARPTR arg2) /* for sort */
  1052. {
  1053.    return(strncasecmp(*((char far * far *)arg1),*((char far *far *)arg2),40));
  1054. }
  1055.  
  1056. void far_strncpy(char far *t, char far *s, int len)
  1057. {
  1058.    while((len-- && (*t++ = *s++) != 0));
  1059. }
  1060.  
  1061. char far *far_strchr(char far *str, char c)
  1062. {
  1063.    int len,i;
  1064.    len = far_strlen(str);
  1065.    i= -1;
  1066.    while (++i < len && c != str[i]);
  1067.    if(i == len)
  1068.       return(NULL);
  1069.    else
  1070.       return(&str[i]);   
  1071. }
  1072.  
  1073. char far *far_strrchr(char far *str, char c)
  1074. {
  1075.    int len;
  1076.    len = far_strlen(str);
  1077.    while (--len > -1 && c != str[len]);
  1078.    if(len == -1)
  1079.       return(NULL);
  1080.    else
  1081.       return(&str[len]);
  1082. }
  1083.  
  1084. /* returns 1 if name a GIF with dimensions x,y */
  1085. int isagif(char *name, int x, int y)
  1086. {
  1087.    BYTE buffer[13];
  1088.    FILE *fp;
  1089.    int width, height, i;
  1090.  
  1091.    if(name == NULL)
  1092.       return(0);
  1093.    if(*name == 0)
  1094.       return(0);      
  1095.    if((fp = fopen(name,"rb"))==NULL)
  1096.       return(0);
  1097.    /* Get the screen description */
  1098.    for (i = 0; i < 13; i++)
  1099.    {
  1100.       int tmp;
  1101.       buffer[i] = (BYTE)(tmp = getc(fp));
  1102.       if (tmp < 0)
  1103.       {
  1104.          fclose(fp);
  1105.          return(0);
  1106.       }
  1107.    }
  1108.    fclose(fp);
  1109.    width  = buffer[6] | (buffer[7] << 8);
  1110.    height = buffer[8] | (buffer[9] << 8);
  1111.  
  1112.    if(strncmp((char *)buffer,"GIF87a",3) || 
  1113.       buffer[3] < '0' || buffer[3] > '9' ||
  1114.       buffer[4] < '0' || buffer[4] > '9' ||
  1115.       buffer[5] < 'A' || buffer[5] > 'z' ||
  1116.       width != x || 
  1117.       height != y )
  1118.       return(0);
  1119.    else
  1120.       return(1);
  1121. }
  1122.  
  1123. static int speedstate;
  1124. int getafilename(char *hdg,char *template,char *flname)
  1125. {
  1126.    int rds;  /* if getting an RDS image map */ 
  1127.    static FCODE o_instr[]={"Press F6 for default directory, F4 to toggle sort "};
  1128.    char far *instr;
  1129.    int masklen;
  1130.    char filename[13];
  1131.    char speedstr[81];
  1132.    char tmpmask[FILE_MAX_PATH];   /* used to locate next file in list */
  1133.    static int numtemplates = 1;
  1134.    int i,j;
  1135.    int out;
  1136.    int retried;
  1137.    static struct CHOICE
  1138.    {
  1139.       char name[13];
  1140.       char type;
  1141.    }
  1142.    far *far*choices;
  1143.    int far *attributes;
  1144.    int filecount;   /* how many files */
  1145.    int dircount;    /* how many directories */
  1146.    int notroot;     /* not the root directory */
  1147.  
  1148.    char drive[FILE_MAX_DRIVE];
  1149.    char dir[FILE_MAX_DIR];
  1150.    char fname[FILE_MAX_FNAME];
  1151.    char ext[FILE_MAX_EXT];
  1152.    static int dosort = 1;
  1153.    int options = 8;
  1154.  
  1155.    rds = (stereomapname == flname)?1:0;
  1156.    if(rds)
  1157.    {
  1158.       setclear();
  1159.       sprintf(speedstr,"Scanning for %dx%d file names...",xdots,ydots);
  1160.       putstringcenter(0,0,80,C_GENERAL_INPUT,speedstr);
  1161.    }     
  1162.    /* steal existing array for "choices" */
  1163.    choices = (struct CHOICE far *far*)MK_FP(extraseg,0);
  1164.    choices[0] = (struct CHOICE far *)(choices + MAXNUMFILES+1);
  1165.    attributes = (int far *)(choices[0] + MAXNUMFILES+1);
  1166.    instr = (char far *)(attributes + MAXNUMFILES +1);
  1167. #if 0 /* not needed if no farmemalloc */
  1168.    if(choices[0] == NULL)
  1169.       stopmsg(0, "farmemalloc failed in getafilename");
  1170. #endif
  1171.    attributes[0] = 1;
  1172.    for(i=1;i<MAXNUMFILES+1;i++)
  1173.    {
  1174.       choices[i] = choices[i-1] + 1;
  1175.       attributes[i] = 1;
  1176.    }
  1177.  
  1178. restart:  /* return here if template or directory changes */
  1179.  
  1180.    tmpmask[0] = 0;
  1181.    if(flname[0] == 0)
  1182.       strcpy(flname,DOTSLASH);
  1183.    splitpath(flname ,drive,dir,fname,ext);
  1184.    makepath(filename,""   ,"" ,fname,ext);
  1185.    retried = 0;
  1186. retry_dir:
  1187.    if (dir[0] == 0)
  1188.       strcpy(dir,".");
  1189.    expand_dirname(dir,drive);
  1190.    makepath(tmpmask,drive,dir,"","");
  1191.    fix_dirname(tmpmask);
  1192.    if (retried == 0 && strcmp(dir,SLASH) && strcmp(dir,DOTSLASH))
  1193.    {
  1194.       tmpmask[(j = strlen(tmpmask) - 1)] = 0; /* strip trailing \ */
  1195.       if (strchr(tmpmask,'*') || strchr(tmpmask,'?')
  1196.     || fr_findfirst(tmpmask) != 0
  1197.     || (DTA.attribute & SUBDIR) == 0)
  1198.       {
  1199.          strcpy(dir,DOTSLASH);
  1200.      ++retried;
  1201.      goto retry_dir;
  1202.       }
  1203.       tmpmask[j] = SLASHC;
  1204.    }
  1205.    if(template[0])
  1206.    {
  1207.       numtemplates = 1;
  1208.       splitpath(template,NULL,NULL,fname,ext);
  1209.    }
  1210.    else
  1211.       numtemplates = sizeof(masks)/sizeof(masks[0]);
  1212.    filecount = -1;
  1213.    dircount  = 0;
  1214.    notroot   = 0;
  1215.    j = 0;
  1216.    masklen = strlen(tmpmask);
  1217.    strcat(tmpmask,"*.*");
  1218.    out = fr_findfirst(tmpmask);
  1219.    while(out == 0 && filecount < MAXNUMFILES)
  1220.    {
  1221.       if((DTA.attribute & SUBDIR) && strcmp(DTA.filename,"."))
  1222.       {
  1223. #ifndef XFRACT
  1224.      strlwr(DTA.filename);
  1225. #endif
  1226.      if(strcmp(DTA.filename,".."))
  1227.             strcat(DTA.filename,SLASH);
  1228.      far_strncpy(choices[++filecount]->name,DTA.filename,13);
  1229.      choices[filecount]->name[12] = '\0';
  1230.      choices[filecount]->type = 1;
  1231.      dircount++;
  1232.      if(strcmp(DTA.filename,"..")==0)
  1233.         notroot = 1;
  1234.       }
  1235.       out = fr_findnext();
  1236.    }
  1237.    tmpmask[masklen] = 0;
  1238.    if(template[0])
  1239.       makepath(tmpmask,drive,dir,fname,ext);
  1240.    do
  1241.    {
  1242.       if(numtemplates > 1)
  1243.      strcpy(&(tmpmask[masklen]),masks[j]);
  1244.       out = fr_findfirst(tmpmask);
  1245.       while(out == 0 && filecount < MAXNUMFILES)
  1246.       {
  1247.      if(!(DTA.attribute & SUBDIR))
  1248.      {
  1249.         if(rds)
  1250.         {
  1251.                sprintf(speedstr,"%s",DTA.filename);
  1252.                putstringcenter(2,0,80,C_GENERAL_INPUT,speedstr);
  1253.  
  1254.                splitpath(DTA.filename,NULL,NULL,fname,ext);
  1255.                /* just using speedstr as a handy buffer */
  1256.                makepath(speedstr,drive,dir,fname,ext);
  1257.                if(isagif(speedstr,xdots,ydots))
  1258.                {
  1259.                   strlwr(DTA.filename);
  1260.               far_strncpy(choices[++filecount]->name,DTA.filename,13);
  1261.               choices[filecount]->type = 0;
  1262.                }
  1263.         }
  1264.         else
  1265.         {
  1266.            strlwr(DTA.filename);
  1267.            far_strncpy(choices[++filecount]->name,DTA.filename,13);
  1268.            choices[filecount]->type = 0;
  1269.             }
  1270.      }
  1271.      out = fr_findnext();
  1272.       }
  1273.    }
  1274.    while (++j < numtemplates);
  1275.    if (++filecount == 0)
  1276.    {
  1277.       far_strcpy(choices[filecount]->name,"*nofiles*");
  1278.       choices[filecount]->type = 0;
  1279.       ++filecount;
  1280.    }
  1281.    
  1282.    far_strcpy(instr,o_instr);
  1283.    if(dosort)
  1284.    {
  1285.       far_strcat(instr,"off");
  1286.       shell_sort((void far *far*)choices,filecount,sizeof(char far *),lccompare); /* sort file list */
  1287.    }
  1288.    else
  1289.       far_strcat(instr,"on");
  1290.    if(notroot == 0 && dir[0] && dir[0] != SLASHC) /* must be in root directory */
  1291.    {
  1292.       splitpath(tmpmask,drive,dir,fname,ext);
  1293.       strcpy(dir,SLASH);
  1294.       makepath(tmpmask,drive,dir,fname,ext);
  1295.    }
  1296.    if(numtemplates > 1)
  1297.    {
  1298.       strcat(tmpmask," ");
  1299.       strcat(tmpmask,masks[0]);
  1300.    }
  1301.    strcpy(temp1,hdg);
  1302.    strcat(temp1,"\nTemplate: ");
  1303.    strcat(temp1,tmpmask);
  1304.    strcpy(speedstr,filename);
  1305.    if (speedstr[0] == 0)
  1306.    {
  1307.       for (i=0; i<filecount; i++) /* find first file */
  1308.      if (choices[i]->type == 0)
  1309.         break;
  1310.       if (i >= filecount)
  1311.      i = 0;
  1312.    }
  1313.    if(dosort)
  1314.       options = 8;
  1315.    else
  1316.       options = 8+32;   
  1317.    i = fullscreen_choice(options,temp1,NULL,instr,filecount,(char far *far*)choices,
  1318.           attributes,5,99,12,i,NULL,speedstr,filename_speedstr,check_f6_key);
  1319.    if (i==-F4)
  1320.    {
  1321.       dosort = 1 - dosort;
  1322.       goto restart;
  1323.    }
  1324.    if (i==-F6)
  1325.    {
  1326.       static int lastdir=0;
  1327.       if (lastdir==0)
  1328.       {
  1329.      strcpy(dir,fract_dir1);
  1330.       }
  1331.       else
  1332.       {
  1333.      strcpy(dir,fract_dir2);
  1334.       }
  1335.       fix_dirname(dir);
  1336.       makepath(flname,drive,dir,"","");
  1337.       lastdir = 1-lastdir;
  1338.       goto restart;
  1339.    }
  1340.    if (i < 0)
  1341.    {
  1342.       return(-1);
  1343.    }
  1344.    if(speedstr[0] == 0 || speedstate == MATCHING)
  1345.    {
  1346.       if(choices[i]->type)
  1347.       {
  1348.      if(far_strcmp(choices[i]->name,"..") == 0) /* go up a directory */
  1349.      {
  1350.         if(strcmp(dir,DOTSLASH) == 0)
  1351.            strcpy(dir,DOTDOTSLASH);
  1352.         else
  1353.         {
  1354.            char *s;
  1355.            if((s = strrchr(dir,SLASHC)) != NULL) /* trailing slash */
  1356.            {
  1357.           *s = 0;
  1358.           if((s = strrchr(dir,SLASHC)) != NULL)
  1359.              *(s+1) = 0;
  1360.            }
  1361.         }
  1362.      }
  1363.      else  /* go down a directory */
  1364.         far_strcat(dir,choices[i]->name);
  1365.      fix_dirname(dir);
  1366.      makepath(flname,drive,dir,"","");
  1367.      goto restart;
  1368.       }
  1369.       splitpath(choices[i]->name,NULL,NULL,fname,ext);
  1370.       makepath(flname,drive,dir,fname,ext);
  1371.    }
  1372.    else
  1373.    {
  1374.       if (speedstate == SEARCHPATH
  1375.     && strchr(speedstr,'*') == 0 && strchr(speedstr,'?') == 0
  1376.     && ((fr_findfirst(speedstr) == 0
  1377.     && (DTA.attribute & SUBDIR))|| strcmp(speedstr,SLASH)==0)) /* it is a directory */
  1378.      speedstate = TEMPLATE;
  1379.      
  1380.       if(speedstate == TEMPLATE)
  1381.       {
  1382.      /* extract from tempstr the pathname and template information,
  1383.         being careful not to overwrite drive and directory if not
  1384.         newly specified */
  1385.      char drive1[FILE_MAX_DRIVE];
  1386.      char dir1[FILE_MAX_DIR];
  1387.      char fname1[FILE_MAX_FNAME];
  1388.      char ext1[FILE_MAX_EXT];
  1389.      splitpath(speedstr,drive1,dir1,fname1,ext1);
  1390.      if(drive1[0])
  1391.         strcpy(drive,drive1);
  1392.      if(dir1[0])
  1393.         strcpy(dir,dir1);
  1394.      makepath(flname,drive,dir,fname1,ext1);
  1395.      if(strchr(fname1,'*') || strchr(fname1,'?') ||
  1396.          strchr(ext1  ,'*') || strchr(ext1  ,'?'))
  1397.         makepath(template,"","",fname1,ext1);
  1398.      else if(isadirectory(flname))
  1399.         fix_dirname(flname);
  1400.      goto restart;
  1401.       }
  1402.       else /* speedstate == SEARCHPATH */
  1403.       {
  1404.      char fullpath[80];
  1405.       /* if (strchr(speedstr,'.') == NULL)
  1406.         strcat(speedstr,masks[1]); */
  1407.      findpath(speedstr,fullpath);
  1408.      if(fullpath[0])
  1409.         strcpy(flname,fullpath);
  1410.      else
  1411.      {  /* failed, make diagnostic useful: */
  1412.         strcpy(flname,speedstr);
  1413.         if (strchr(speedstr,SLASHC) == NULL)
  1414.         {
  1415.            splitpath(speedstr,NULL,NULL,fname,ext);
  1416.            makepath(flname,drive,dir,fname,ext);
  1417.         }
  1418.      }
  1419.       }
  1420.    }
  1421.    makepath(browsename,"","",fname,ext);
  1422.    return(0);
  1423. }
  1424.  
  1425. #ifdef __CLINT__
  1426. #pragma argsused
  1427. #endif
  1428.  
  1429. static int check_f6_key(int curkey,int choice)
  1430. { /* choice is dummy used by other routines called by fullscreen_choice() */
  1431.    choice = 0; /* to suppress warning only */
  1432.    if (curkey == F6)
  1433.       return 0-F6;
  1434.    else if (curkey == F4)
  1435.       return 0-F4;
  1436.    return 0;
  1437. }
  1438.  
  1439. static int filename_speedstr(int row, int col, int vid,
  1440.                  char *speedstring, int speed_match)
  1441. {
  1442.    char *prompt;
  1443.    if ( strchr(speedstring,':')
  1444.      || strchr(speedstring,'*') || strchr(speedstring,'*')
  1445.      || strchr(speedstring,'?')) {
  1446.       speedstate = TEMPLATE;  /* template */
  1447.       prompt = "File Template";
  1448.       }
  1449.    else if (speed_match) {
  1450.       speedstate = SEARCHPATH; /* does not match list */
  1451.       prompt = "Search Path for";
  1452.       }
  1453.    else {
  1454.       speedstate = MATCHING;
  1455.       prompt = speed_prompt;
  1456.       }
  1457.    putstring(row,col,vid,prompt);
  1458.    return(strlen(prompt));
  1459. }
  1460.  
  1461. int isadirectory(char *s)
  1462. {
  1463.    int len;
  1464.    char sv;
  1465. #ifdef _MSC_VER
  1466.    unsigned attrib = 0;
  1467. #endif
  1468.    despace(s);  /* scrunch out white space */
  1469.    if(strchr(s,'*') || strchr(s,'?'))
  1470.       return(0); /* for my purposes, not a directory */
  1471.  
  1472.    len = strlen(s);
  1473.    if(len > 0)
  1474.       sv = s[len-1];   /* last char */
  1475.    else
  1476.       sv = 0;
  1477.  
  1478. #ifdef _MSC_VER
  1479.    if(_dos_getfileattr(s, &attrib) == 0 && ((attrib&_A_SUBDIR) != 0))
  1480.    {
  1481.       return(1);  /* not a directory or doesn't exist */
  1482.    }
  1483.    else if(sv == SLASHC)
  1484.    {
  1485.       /* strip trailing slash and try again */
  1486.       s[len-1] = 0;
  1487.       if(_dos_getfileattr(s, &attrib) == 0 && ((attrib&_A_SUBDIR) != 0))
  1488.       {
  1489.          s[len-1] = sv;
  1490.          return(1);  
  1491.       }
  1492.       s[len-1] = sv;
  1493.    }
  1494.    return(0);
  1495. #else
  1496.    if(fr_findfirst(s) != 0) /* couldn't find it */
  1497.    {
  1498.       /* any better ideas?? */
  1499.       if(strchr(s,SLASHC)) /* we'll guess it is a directory */
  1500.      return(1);
  1501.       else
  1502.      return(0);  /* no slashes - we'll guess it's a file */
  1503.    }
  1504.    else if(DTA.attribute & SUBDIR)
  1505.       return(1);   /* we're SURE it's a directory */
  1506.    else
  1507.       return(0);
  1508. #endif
  1509. }
  1510.  
  1511.  
  1512. #ifndef XFRACT    /* This routine moved to unix.c so we can use it in hc.c */
  1513.  
  1514. int splitpath(char far *template,char *drive,char *dir,char *fname,char *ext)
  1515. {
  1516.    int length;
  1517.    int len;
  1518.    int offset;
  1519.    char far *tmp;
  1520.    if(drive)
  1521.       drive[0] = 0;
  1522.    if(dir)
  1523.       dir[0]   = 0;
  1524.    if(fname)
  1525.       fname[0] = 0;
  1526.    if(ext)
  1527.       ext[0]   = 0;
  1528.  
  1529.    if((length = far_strlen(template)) == 0)
  1530.       return(0);
  1531.  
  1532.    offset = 0;
  1533.  
  1534.    /* get drive */
  1535.    if(length >= 2)
  1536.       if(template[1] == ':')
  1537.       {
  1538.      if(drive)
  1539.      {
  1540.         drive[0] = template[offset++];
  1541.         drive[1] = template[offset++];
  1542.         drive[2] = 0;
  1543.      }
  1544.      else
  1545.      {
  1546.         offset++;
  1547.         offset++;
  1548.      }
  1549.       }
  1550.  
  1551.    /* get dir */
  1552.    if(offset < length)
  1553.    {
  1554.       tmp = far_strrchr(template,SLASHC);
  1555.       if(tmp)
  1556.       {
  1557.      tmp++;  /* first character after slash */
  1558.      len = tmp - (char far *)&template[offset];
  1559.      if(len >= 0 && len < FILE_MAX_DIR && dir)
  1560.         far_strncpy(dir,&template[offset],min(len,FILE_MAX_DIR));
  1561.      if(len < FILE_MAX_DIR && dir)
  1562.         dir[len] = 0;
  1563.      offset += len;
  1564.       }
  1565.    }
  1566.    else
  1567.       return(0);
  1568.  
  1569.    /* get fname */
  1570.    if(offset < length)
  1571.    {
  1572.       tmp = far_strrchr(template,'.');
  1573.       if(tmp < far_strrchr(template,SLASHC) || tmp < far_strrchr(template,':'))
  1574.      tmp = 0; /* in this case the '.' must be a directory */
  1575.       if(tmp)
  1576.       {
  1577.      /* tmp++; */ /* first character past "." */
  1578.      len = tmp - (char far *)&template[offset];
  1579.      if((len > 0) && (offset+len < length) && fname)
  1580.      {
  1581.         far_strncpy(fname,&template[offset],min(len,FILE_MAX_FNAME));
  1582.         if(len < FILE_MAX_FNAME)
  1583.            fname[len] = 0;
  1584.         else
  1585.            fname[FILE_MAX_FNAME-1] = 0;   
  1586.      }
  1587.      offset += len;
  1588.      if((offset < length) && ext)
  1589.          {
  1590.         far_strncpy(ext,&template[offset],FILE_MAX_EXT);
  1591.             ext[FILE_MAX_EXT-1] = 0;
  1592.          }
  1593.       }
  1594.       else if((offset < length) && fname)
  1595.       {
  1596.      far_strncpy(fname,&template[offset],FILE_MAX_FNAME);
  1597.          fname[FILE_MAX_FNAME-1] = 0;   
  1598.       }
  1599.    }
  1600.    return(0);
  1601. }
  1602. #endif
  1603.  
  1604. makepath(char *template,char *drive,char *dir,char *fname,char *ext)
  1605. {
  1606.    if(template)
  1607.       *template = 0;
  1608.    else
  1609.       return(-1);   
  1610. #ifndef XFRACT
  1611.    if(drive)
  1612.       strcpy(template,drive);
  1613. #endif
  1614.    if(dir)
  1615.       strcat(template,dir);
  1616.    if(fname)
  1617.       strcat(template,fname);
  1618.    if(ext)
  1619.       strcat(template,ext);
  1620.    return(0);
  1621. }
  1622.  
  1623.  
  1624. /* fix up directory names */
  1625. void fix_dirname(char *dirname)
  1626. {
  1627.    int length;
  1628.    despace(dirname);
  1629.    length = strlen(dirname); /* index of last character */
  1630.  
  1631.    /* make sure dirname ends with a slash */
  1632.    if(length > 0)
  1633.       if(dirname[length-1] == SLASHC)
  1634.          return;
  1635.    strcat(dirname,SLASH);
  1636. }
  1637.  
  1638. static void dir_name(char *target, char *dir, char *name)
  1639. {
  1640.    *target = 0;
  1641.    if(*dir != 0)
  1642.       strcpy(target,dir);
  1643.    strcat(target,name);
  1644. }
  1645.  
  1646. /* opens file in dir directory */ 
  1647. int dir_open(char *dir, char *filename, int oflag, int pmode)
  1648. {
  1649.    char tmp[FILE_MAX_PATH];
  1650.    dir_name(tmp,dir,filename);
  1651.    return(open(tmp,oflag,pmode));
  1652. }
  1653.  
  1654. /* removes file in dir directory */ 
  1655. int dir_remove(char *dir,char *filename)
  1656. {
  1657.    char tmp[FILE_MAX_PATH];
  1658.    dir_name(tmp,dir,filename);
  1659.    return(remove(tmp));
  1660. }
  1661.  
  1662. /* fopens file in dir directory */ 
  1663. FILE *dir_fopen(char *dir, char *filename, char *mode )
  1664. {
  1665.    char tmp[FILE_MAX_PATH];
  1666.    dir_name(tmp,dir,filename);
  1667.    return(fopen(tmp,mode));
  1668. }
  1669.  
  1670. /* converts relative path to absolute path */
  1671. static int expand_dirname(char *dirname,char *drive)
  1672. {
  1673.    fix_dirname(dirname);
  1674.    if (dirname[0] != SLASHC) {
  1675.       char buf[81],curdir[81];
  1676. #ifndef XFRACT
  1677.       union REGS regs;
  1678.       struct SREGS sregs;
  1679.       curdir[0] = 0;
  1680.       regs.h.ah = 0x47; /* get current directory */
  1681.       regs.h.dl = 0;
  1682.       if (drive[0] && drive[0] != ' ')
  1683.      regs.h.dl = (char)(tolower(drive[0])-'a'+1);
  1684.       regs.x.si = (unsigned int) &curdir[0];
  1685.       segread(&sregs);
  1686.       intdosx(®s, ®s, &sregs);
  1687. #else
  1688.       getwd(curdir);
  1689. #endif
  1690.       strcat(curdir,SLASH);
  1691.       while (strncmp(dirname,DOTSLASH,2) == 0) {
  1692.      strcpy(buf,&dirname[2]);
  1693.      strcpy(dirname,buf);
  1694.      }
  1695.       while (strncmp(dirname,DOTDOTSLASH,3) == 0) {
  1696.      char *s;
  1697.      curdir[strlen(curdir)-1] = 0; /* strip trailing slash */
  1698.      if ((s = strrchr(curdir,SLASHC)) != NULL)
  1699.         *s = 0;
  1700.      strcat(curdir,SLASH);
  1701.      strcpy(buf,&dirname[3]);
  1702.      strcpy(dirname,buf);
  1703.      }
  1704.       strcpy(buf,dirname);
  1705.       dirname[0] = 0;
  1706.       if (curdir[0] != SLASHC)
  1707.      strcpy(dirname,SLASH);
  1708.       strcat(dirname,curdir);
  1709.       strcat(dirname,buf);
  1710.       }
  1711.    return(0);
  1712. }
  1713.  
  1714.    
  1715. /* 
  1716.    See if double value was changed by input screen. Problem is that the 
  1717.    conversion from double to string and back can make small changes
  1718.    in the value, so will it twill test as "different" even though it
  1719.    is not
  1720. */
  1721. int cmpdbl(double old, double new)
  1722. {
  1723.    char buf[81];
  1724.    struct fullscreenvalues val;
  1725.  
  1726.    /* change the old value with the same torture the new value had */
  1727.    val.type = 'd'; /* most values on this screen are type d */
  1728.    val.uval.dval = old;
  1729.    prompt_valuestring(buf,&val);   /* convert "old" to string */
  1730.  
  1731.    old = atof(buf);                /* convert back */
  1732.    return(fabs(old-new)<DBL_EPSILON?0:1);  /* zero if same */  
  1733. }
  1734.  
  1735. #define LOADPROMPTS(X)     {\
  1736.    static FCODE tmp[] = { X };\
  1737.    far_strcpy(ptr,(char far *)tmp);\
  1738.    prompts[++nump]= ptr;\
  1739.    ptr += sizeof(tmp);\
  1740.    }
  1741.  
  1742. int get_corners()
  1743. {
  1744.    char far *ptr;
  1745.    struct fullscreenvalues values[15];
  1746.    char far *prompts[15];
  1747.    static FCODE o_xprompt[]={"          X"};
  1748.    static FCODE o_yprompt[]={"          Y"};
  1749.    static FCODE o_zprompt[]={"          Z"};
  1750.    char xprompt[sizeof(o_xprompt)];
  1751.    char yprompt[sizeof(o_yprompt)];
  1752.    char zprompt[sizeof(o_zprompt)];
  1753.    int i,nump,prompt_ret;
  1754.    int cmag;
  1755.    double Xctr,Yctr;
  1756.    LDBL Magnification; /* LDBL not really needed here, but used to match function parameters */
  1757.    double Xmagfactor,Rotation,Skew;
  1758.    BYTE ousemag;
  1759.    double oxxmin,oxxmax,oyymin,oyymax,oxx3rd,oyy3rd;
  1760.    static FCODE hdg[]={"Image Coordinates"};
  1761.    int oldhelpmode;
  1762.  
  1763.    far_strcpy(xprompt,o_xprompt);
  1764.    far_strcpy(yprompt,o_yprompt);
  1765.    far_strcpy(zprompt,o_zprompt);
  1766.    ptr = (char far *)MK_FP(extraseg,0);
  1767.    oldhelpmode = helpmode;
  1768.    ousemag = usemag;
  1769.    oxxmin = xxmin; oxxmax = xxmax;
  1770.    oyymin = yymin; oyymax = yymax;
  1771.    oxx3rd = xx3rd; oyy3rd = yy3rd;
  1772.  
  1773. gc_loop:
  1774.    for (i = 0; i < 15; ++i)
  1775.       values[i].type = 'd'; /* most values on this screen are type d */
  1776.    cmag = usemag;
  1777.    cvtcentermag(&Xctr, &Yctr, &Magnification, &Xmagfactor, &Rotation, &Skew);
  1778.  
  1779.    nump = -1;
  1780.    if (cmag) {
  1781.       LOADPROMPTS("Center X");
  1782.       values[nump].uval.dval = Xctr;
  1783.       LOADPROMPTS("Center Y");
  1784.       values[nump].uval.dval = Yctr;
  1785.       LOADPROMPTS("Magnification");
  1786.       values[nump].uval.dval = (double)Magnification;
  1787.       LOADPROMPTS("X Magnification Factor");
  1788.       values[nump].uval.dval = Xmagfactor;
  1789.       LOADPROMPTS("Rotation Angle (degrees)");
  1790.       values[nump].uval.dval = Rotation;
  1791.       LOADPROMPTS("Skew Angle (degrees)");
  1792.       values[nump].uval.dval = Skew;
  1793.       LOADPROMPTS("");
  1794.       values[nump].type = '*';
  1795.       LOADPROMPTS("Press F7 to switch to \"corners\" mode");
  1796.       values[nump].type = '*';
  1797.       }
  1798.  
  1799.    else {
  1800.       LOADPROMPTS("Top-Left Corner");
  1801.       values[nump].type = '*';
  1802.       prompts[++nump] = xprompt;
  1803.       values[nump].uval.dval = xxmin;
  1804.       prompts[++nump] = yprompt;
  1805.       values[nump].uval.dval = yymax;
  1806.       LOADPROMPTS("Bottom-Right Corner");
  1807.       values[nump].type = '*';
  1808.       prompts[++nump] = xprompt;
  1809.       values[nump].uval.dval = xxmax;
  1810.       prompts[++nump] = yprompt;
  1811.       values[nump].uval.dval = yymin;
  1812.       if (xxmin == xx3rd && yymin == yy3rd)
  1813.          xx3rd = yy3rd = 0;
  1814.       LOADPROMPTS("Bottom-left (zeros for top-left X, bottom-right Y)");
  1815.       values[nump].type = '*';
  1816.       prompts[++nump] = xprompt;
  1817.       values[nump].uval.dval = xx3rd;
  1818.       prompts[++nump] = yprompt;
  1819.       values[nump].uval.dval = yy3rd;
  1820.       LOADPROMPTS("Press F7 to switch to \"center-mag\" mode");
  1821.       values[nump].type = '*';
  1822.    }
  1823.  
  1824.    LOADPROMPTS("Press F4 to reset to type default values");
  1825.    values[nump].type = '*';
  1826.  
  1827.    oldhelpmode = helpmode;
  1828.    helpmode = HELPCOORDS;
  1829.    prompt_ret = fullscreen_prompt(hdg,nump+1, prompts, values, 0x90, NULL);
  1830.    helpmode = oldhelpmode;
  1831.  
  1832.    if (prompt_ret < 0) {
  1833.       usemag = ousemag;
  1834.       xxmin = oxxmin; xxmax = oxxmax;
  1835.       yymin = oyymin; yymax = oyymax;
  1836.       xx3rd = oxx3rd; yy3rd = oyy3rd;
  1837.       return(-1);
  1838.       }
  1839.  
  1840.    if (prompt_ret == F4) { /* reset to type defaults */
  1841.       xx3rd = xxmin = curfractalspecific->xmin;
  1842.       xxmax        = curfractalspecific->xmax;
  1843.       yy3rd = yymin = curfractalspecific->ymin;
  1844.       yymax        = curfractalspecific->ymax;
  1845.       if (viewcrop && finalaspectratio != screenaspect)
  1846.      aspectratio_crop(screenaspect,finalaspectratio);
  1847.       goto gc_loop;
  1848.       }
  1849.  
  1850.    if (cmag) {
  1851.       if ( cmpdbl(Xctr         , values[0].uval.dval)
  1852.         || cmpdbl(Yctr         , values[1].uval.dval)
  1853.         || cmpdbl((double)Magnification, values[2].uval.dval)
  1854.         || cmpdbl(Xmagfactor   , values[3].uval.dval)
  1855.         || cmpdbl(Rotation     , values[4].uval.dval)
  1856.         || cmpdbl(Skew         , values[5].uval.dval))
  1857.       {
  1858.          Xctr          = values[0].uval.dval;
  1859.          Yctr          = values[1].uval.dval;
  1860.          Magnification = values[2].uval.dval;
  1861.          Xmagfactor    = values[3].uval.dval;
  1862.          Rotation      = values[4].uval.dval;
  1863.          Skew          = values[5].uval.dval;
  1864.          if (Xmagfactor == 0)
  1865.             Xmagfactor = 1;
  1866.          cvtcorners(Xctr, Yctr, Magnification, Xmagfactor, Rotation, Skew);
  1867.       }
  1868.    }
  1869.  
  1870.    else {
  1871.       nump = 1;
  1872.       xxmin = values[nump++].uval.dval;
  1873.       yymax = values[nump++].uval.dval;
  1874.       nump++;
  1875.       xxmax = values[nump++].uval.dval;
  1876.       yymin = values[nump++].uval.dval;
  1877.       nump++;
  1878.       xx3rd = values[nump++].uval.dval;
  1879.       yy3rd = values[nump++].uval.dval;
  1880.       if (xx3rd == 0 && yy3rd == 0) {
  1881.          xx3rd = xxmin;
  1882.          yy3rd = yymin;
  1883.       }
  1884.    }
  1885.  
  1886.    if (prompt_ret == F7) { /* toggle corners/center-mag mode */
  1887.       if (usemag == 0)
  1888.       {
  1889.          cvtcentermag(&Xctr, &Yctr, &Magnification, &Xmagfactor, &Rotation, &Skew);
  1890.         usemag = 1;
  1891.       }
  1892.       else
  1893.      usemag = 0;
  1894.       goto gc_loop;
  1895.       }
  1896.  
  1897.    if(!cmpdbl(oxxmin,xxmin) && !cmpdbl(oxxmax,xxmax) && !cmpdbl(oyymin,yymin) && 
  1898.       !cmpdbl(oyymax,yymax) && !cmpdbl(oxx3rd,xx3rd) && !cmpdbl(oyy3rd,yy3rd))
  1899.    {
  1900.      /* no change, restore values to avoid drift */ 
  1901.       xxmin = oxxmin; xxmax = oxxmax;
  1902.       yymin = oyymin; yymax = oyymax;
  1903.       xx3rd = oxx3rd; yy3rd = oyy3rd;
  1904.       return 0;
  1905.    }
  1906.    else
  1907.       return(1);
  1908. }
  1909.  
  1910. /* get browse parameters , called from fractint.c and loadfile.c
  1911.    returns 3 if anything changes.  code pinched from get_view_params */
  1912.  
  1913. int get_browse_params()
  1914. {
  1915.    static FCODE o_hdg[]={"Browse ('L'ook) Mode Options"};
  1916.    char hdg[sizeof(o_hdg)];
  1917.    char far *ptr;
  1918.    char far *choices[10];
  1919.  
  1920.    int oldhelpmode;
  1921.    struct fullscreenvalues uvalues[25];
  1922.    int i, k;
  1923.    int old_autobrowse,old_brwschecktype,old_brwscheckparms,old_doublecaution;
  1924.    int old_minbox;
  1925.    double old_toosmall;
  1926.    char old_browsemask[13];
  1927.  
  1928.    far_strcpy(hdg,o_hdg);
  1929.    ptr = (char far *)MK_FP(extraseg,0);
  1930.    old_autobrowse     = autobrowse;
  1931.    old_brwschecktype  = brwschecktype;
  1932.    old_brwscheckparms = brwscheckparms;
  1933.    old_doublecaution  = doublecaution;
  1934.    old_minbox         = minbox;
  1935.    old_toosmall       = toosmall;
  1936.    strcpy(old_browsemask,browsemask);
  1937.  
  1938. get_brws_restart:
  1939.    /* fill up the previous values arrays */
  1940.    k = -1;
  1941.  
  1942.    LOADCHOICES("Autobrowsing? (y/n)");
  1943.    uvalues[k].type = 'y';
  1944.    uvalues[k].uval.ch.val = autobrowse;
  1945.  
  1946.    LOADCHOICES("Ask about GIF video mode? (y/n)");
  1947.    uvalues[k].type = 'y';
  1948.    uvalues[k].uval.ch.val = askvideo;
  1949.  
  1950.    LOADCHOICES("Check fractal type? (y/n)");
  1951.    uvalues[k].type = 'y';
  1952.    uvalues[k].uval.ch.val = brwschecktype;
  1953.  
  1954.    LOADCHOICES("Check fractal parameters (y/n)");
  1955.    uvalues[k].type = 'y';
  1956.    uvalues[k].uval.ch.val = brwscheckparms;
  1957.  
  1958.    LOADCHOICES("Confirm file deletes (y/n)" );
  1959.    uvalues[k].type='y';
  1960.    uvalues[k].uval.ch.val = doublecaution;
  1961.  
  1962.    LOADCHOICES("Smallest window to display (size in pixels)");
  1963.    uvalues[k].type = 'f';
  1964.    uvalues[k].uval.dval = toosmall;
  1965.  
  1966.    LOADCHOICES("Smallest box size shown before crosshairs used (pix)");
  1967.    uvalues[k].type = 'i';
  1968.    uvalues[k].uval.ival = minbox;
  1969.     LOADCHOICES("Browse search filename mask ");
  1970.    uvalues[k].type = 's';
  1971.    strcpy(uvalues[k].uval.sval,browsemask);
  1972.  
  1973.    LOADCHOICES("");
  1974.    uvalues[k].type = '*';
  1975.  
  1976.    LOADCHOICES("Press F4 to reset browse parameters to defaults.");
  1977.    uvalues[k].type = '*';
  1978.  
  1979.    oldhelpmode = helpmode;     /* this prevents HELP from activating */
  1980.    helpmode = HELPBRWSPARMS;
  1981.    i = fullscreen_prompt(hdg,k+1,choices,uvalues,16,NULL);
  1982.    helpmode = oldhelpmode;     /* re-enable HELP */
  1983.    if (i < 0) {
  1984.       return(0);
  1985.       }
  1986.  
  1987.    if (i == F4) {
  1988.       toosmall = 6;
  1989.       autobrowse = FALSE;
  1990.       askvideo = TRUE;
  1991.       brwscheckparms = TRUE;
  1992.       brwschecktype  = TRUE;
  1993.       doublecaution  = TRUE;
  1994.       minbox = 3;
  1995.       strcpy(browsemask,"*.gif");
  1996.       goto get_brws_restart;
  1997.       }
  1998.  
  1999.    /* now check out the results (*hopefully* in the same order <grin>) */
  2000.    k = -1;
  2001.  
  2002.    autobrowse = uvalues[++k].uval.ch.val;
  2003.  
  2004.    askvideo = uvalues[++k].uval.ch.val;
  2005.  
  2006.    brwschecktype = (char)uvalues[++k].uval.ch.val;
  2007.  
  2008.    brwscheckparms = (char)uvalues[++k].uval.ch.val;
  2009.  
  2010.    doublecaution = uvalues[++k].uval.ch.val;
  2011.  
  2012.    toosmall  = uvalues[++k].uval.dval;
  2013.    if (toosmall < 0 ) toosmall = 0 ;
  2014.  
  2015.    minbox = uvalues[++k].uval.ival;
  2016.      if (minbox < 1 ) minbox = 1;
  2017.      if (minbox > 10) minbox = 10;
  2018.  
  2019.    strcpy(browsemask,uvalues[++k].uval.sval);
  2020.  
  2021.    i = 0;
  2022.    if (autobrowse != old_autobrowse ||
  2023.        brwschecktype != old_brwschecktype ||
  2024.        brwscheckparms != old_brwscheckparms ||
  2025.        doublecaution != old_doublecaution ||
  2026.        toosmall != old_toosmall ||
  2027.        minbox != old_minbox ||
  2028.        !stricmp(browsemask,old_browsemask) )
  2029.         i = -3;
  2030.  
  2031.    return(i);
  2032. }
  2033.  
  2034. /* merge existing full path with new one  */
  2035. /* attempt to detect if file or directory */
  2036.  
  2037. #define ATFILENAME 0
  2038. #define SSTOOLSINI 1
  2039. #define ATCOMMANDINTERACTIVE 2
  2040. #define ATFILENAMESETNAME  3
  2041.  
  2042. #define GETPATH (mode < 2) 
  2043.  
  2044. /* copies the proposed new filename to the fullpath variable */
  2045. /* does not copy directories for PAR files (modes 2 and 3)   */
  2046. /* attempts to extract directory and test for existence (modes 0 and 1) */
  2047. int merge_pathnames(char *oldfullpath, char *newfilename, int mode)
  2048. {
  2049.    int isadir = 0;
  2050.    int isafile = 0;
  2051.    int len;
  2052.    char drive[FILE_MAX_DRIVE];
  2053.    char dir[FILE_MAX_DIR];
  2054.    char fname[FILE_MAX_FNAME];
  2055.    char ext[FILE_MAX_EXT];
  2056.  
  2057.    char drive1[FILE_MAX_DRIVE];
  2058.    char dir1[FILE_MAX_DIR];
  2059.    char fname1[FILE_MAX_FNAME];
  2060.    char ext1[FILE_MAX_EXT];
  2061.  
  2062.    /* no dot or slash so assume a file */
  2063.    if(strchr(newfilename,'.')==NULL && strchr(newfilename,SLASHC) == NULL)  
  2064.       isafile=1;
  2065.    /* if slash by itself, it's a directory */
  2066.    if(strcmp(newfilename,SLASH)==0)
  2067.       isadir = 1;
  2068. #ifndef XFRACT
  2069.    /* if drive, colon, slash, is a directory */
  2070.    if(strlen(newfilename) == 3 && 
  2071.            newfilename[1] == ':' && 
  2072.            newfilename[2] == SLASHC)
  2073.       isadir = 1;
  2074. #endif
  2075.    /* check existence */
  2076.    if(isadir==0 || isafile==1)
  2077.    {
  2078.        if(fr_findfirst(newfilename) == 0)
  2079.           if(DTA.attribute & SUBDIR) /* exists and is dir */
  2080.           {   
  2081.              fix_dirname(newfilename);  /* add trailing slash */   
  2082.              isadir = 1;
  2083.              isafile = 0;
  2084.           }
  2085.           else
  2086.              isafile = 1;
  2087.    }
  2088.  
  2089.    splitpath(newfilename,drive,dir,fname,ext);
  2090.    splitpath(oldfullpath,drive1,dir1,fname1,ext1);
  2091.    if(strlen(drive) != 0 && GETPATH)
  2092.       strcpy(drive1,drive);
  2093.    if(strlen(dir) != 0 && GETPATH)
  2094.       strcpy(dir1,dir);
  2095.    if(strlen(fname) != 0)
  2096.       strcpy(fname1,fname);
  2097.    if(strlen(ext) != 0)
  2098.       strcpy(ext1,ext);
  2099.    if(isadir == 0 && isafile == 0 && GETPATH)
  2100.    {
  2101.       makepath(oldfullpath,drive1,dir1,NULL,NULL);
  2102.       len = strlen(oldfullpath);
  2103.       if(len > 0)
  2104.       {
  2105.          char save;
  2106.          /* strip trailing slash */
  2107.          save = oldfullpath[len-1];
  2108.          if(save == SLASHC)
  2109.             oldfullpath[len-1] = 0;
  2110.          if(access(oldfullpath,0))
  2111.             isadir = -1;
  2112.          oldfullpath[len-1] = save;
  2113.       }
  2114.    }  
  2115.    makepath(oldfullpath,drive1,dir1,fname1,ext1);
  2116.    return(isadir);
  2117. }
  2118.  
  2119. /* extract just the filename/extension portion of a path */
  2120. void extract_filename(char *target, char *source)
  2121. {
  2122.    char fname[FILE_MAX_FNAME];
  2123.    char ext[FILE_MAX_EXT];
  2124.    splitpath(source,NULL,NULL,fname,ext);
  2125.    makepath(target,"","",fname,ext);
  2126. }
  2127.  
  2128. /* I tried heap sort also - this is faster! */
  2129. void shell_sort(void far *v1, int n, unsigned sz, int (__cdecl *fct)(VOIDFARPTR arg1,VOIDFARPTR arg2))
  2130. {
  2131.    int gap,i,j;
  2132.    void far *temp;
  2133.    char far *v;
  2134.    v = (char far *)v1;
  2135.    for(gap = n/2; gap > 0; gap /= 2)
  2136.       for(i = gap; i<n; i++)
  2137.          for(j=i-gap;j>=0; j -= gap)
  2138.          {
  2139.             if(fct((char far *far*)(v+j*sz),(char far *far*)(v+(j+gap)*sz)) <= 0)
  2140.                break;
  2141.             temp = *(char far *far*)(v+j*sz);
  2142.             *(char far *far*)(v+j*sz) = *(char far *far*)(v+(j+gap)*sz);
  2143.             *(char far *far*)(v+(j+gap)*sz) = temp;   
  2144.          }
  2145. }
  2146.